#!/bin/bash #set -euo pipefail
# -gcc_commit
# -app_commit
# -gcc_repo
# -app_repo

. $LKP_SRC/lib/reproduce_log.sh . $LKP_SRC/lib/debug.sh . $LKP_SRC/lib/git.sh

nix_user="nix"
nix_pwd="nix"
nixpkg_ver="2.4"
#gcc_major_ver="8"
#gcc_minor_ver="2.0"
#gcc_commit="6184085fc664265dc78fd1ad4204c0cbef202628
# 8.2
#gcc_commit="9fb89fa845c1b2e0a18d85ada0b077c84508ab78"
# 8.4.0
#gcc_commit="8cd3bffead2ed1d1998c190865694f920fbc93ab"
# 10.1.1
#gcc_commit="08e068265e463ff5ee4263bec9f4cb207ef9716b"
# 11.1.0
gcc_commit="50bc9185c2821350f0b785d6e23a6e9dcde58466"
# 9.2.1
#gcc_commit="f7589b1c8b7045ee4f5bdf033e05af3fa607c2f2"

mirror_base="https://mirrors.tuna.tsinghua.edu.cn"
gcc_repo="https://gitee.com/mirrors/gcc/repository/archive/"
app_repo="https://gitee.com/barbo/nginx/repository/archive/"

app_name="nginx"
app_commit="83e92a2edd6bfc6867b653284ac44962c4e33c9"

check_valid()
{
  ([ -n "$gcc_commit" ] && [ -n "$gcc_repo" ]) || die "gcc commit or gcc repo is empty"
  [ -n "$app_commit" ] || die "app_commit is empty"
  [ -n "$app_repo" ] || die "app_repo is empty"
  [ -n "$gcc_repo" ] && [ ] || die "gcc_repo is empty"
  local root_fs_type=$(df -T | awk '$7~/\/$/ {print $2}')
  [ $root_fs_type != "rootfs" ] || die "nix can not be installed under root directory with rootfs type"
}

uninstall_nix_env()
{
  if [ -d "/nix" ];then
    rm -rf /nix
    if [ -f /home/${nix_user}/.config/nix/nix.conf ];then
      rm -f /home/${nix_user}/.config/nix/nix.conf
    fi
    echo "uninstall nix environment "
  fi
  if [ ! -e "/usr/bin/tar" ];then
    yum install -y tar || die "failed to install target package"
  fi
}

create_nix_user()
{
  id $nix_user &>/dev/null
  if [ $? -ne 0 ];then
    useradd -m $nix_user || die "failed to create user nix "
    echo $nix_pwd | passwd $nix_user --stdin &>/dev/null || die "failed to set nix's password"
    chmod +x /etc/sudoers && sed -i '/^root/a\nix     ALL=(ALL)       ALL' /etc/sudoers
  fi
}

install_nix()
{
  local arch=$(uname -m)
  local nix_url="${mirror_base}/nix/nix-${nixpkg_ver}/nix-${nixpkg_ver}-${arch}-linux.tar.xz"
  local nix_channel="${mirror_base}/nix-channels/nixpkgs-unstable nixpkgs"
  local nix_profile_path="/home/$nix_user/.nix-profile/bin"

  mkdir -p /nix && chmod -R 777 /nix
   
  echo "---------start the nix installation-----------"
  if [ ! -d nix-${nixpkg_ver}-${arch}-linux ];then
    wget -q $nix_url || die "failed to download nix package"
    tar xJf nix-${nixpkg_ver}-${arch}-linux.tar.xz
  fi
  cd nix-${nixpkg_ver}-${arch}-linux
  su $nix_user <<EOF
./install --no-channel-add
source /home/${nix_user}/.nix-profile/etc/profile.d/nix.sh
${nix_profile_path}/nix-channel --add $nix_channel
${nix_profile_path}/nix-channel --update
EOF
}

setup_nix_config()
{
  local nix_channel="${mirror_base}/nix-channels/store"
  #local nix_channel="https://mirrors.ustc.edu.cn/nix-channels/store"
  su $nix_user <<EOF
mkdir -p /home/${nix_user}/.config/nix 
echo "substituters = $nix_channel" > /home/${nix_user}/.config/nix/nix.conf
EOF
  if [[ ${nixpkg_ver} == "2.4" || ${nixpkg_ver} > "2.4" ]];then
    echo "experimental-features = nix-command" >> /home/${nix_user}/.config/nix/nix.conf 
  fi
}
// $1:commit $2 url $3:pkgname
download_pkg()
{
  if [ ! -f "$LKP_SRC/tests/$1.zip" ];then
    wget -c -O $LKP_SRC/tests/$1.zip $2 || die "failed to download $3 package"
  fi
}

get_gcc_version_info()
{
  echo yes | unzip -j $LKP_SRC/tests/${gcc_commit}.zip gcc-${gcc_commit}/gcc/BASE-VER
  gcc_version=$(cat BASE-VER)
  gcc_major_ver=$(cat BASE-VER | awk -F '.' '{print $1}')
}
#get_app_version_info()
#{
#  app_version=${}
#}

init()
{
  mkdir -p $LKP_SRC/tests/overlays && overlays_path=$LKP_SRC/tests/overlays
  mkdir -p $LKP_SRC/tests/nix-build && nix_build_path=$LKP_SRC/tests/nix-build
  # download gcc package
  if [ -n "$gcc_commit" ];then
    local gcc_url=${gcc_repo}${gcc_commit}.zip
    download_pkg $gcc_commit $gcc_url gcc
    get_gcc_version_info
  fi
  
  # download app package
  if [ -n "$app_commit" ];then
    app_url=${app_repo}${app_commit}.zip
    download_pkg $app_commit $app_url $app_name
  fi
}

find_conflict_insert_point()
{
  add_patch=0
  if [[ ${gcc_major_ver} -eq 7 || ${gcc_major_ver} -eq 8 || ${gcc_major_ver} -eq 11 ]];then
    commits_file=$LKP_SRC/tests/gcc-commits/gcc${gcc_major_ver}-commits
    mapfile commits_array <$commits_file
    declare -A gcc_commits_map
    for i in ${commits_array[@]}
    do
      gcc_commits_map[$i]=1
    done
    if [[ -n ${gcc_commits_map[$gcc_commit]} ]];then
      add_patch=1
    fi
  fi
}
generate_gcc_overlays()
{
  local patch_path=$LKP_SRC/tests/patch
  cat <<EOF> ${overlays_path}/gcc_overlay.nix
self: pkgs:
with pkgs;
{
  gcc${gcc_major_ver} = lowPrio (wrapCC (gcc${gcc_major_ver}.cc.overrideAttrs(oldAttrs: rec {
    name = "gcc-${gcc_commit}";
    version = "${gcc_version}";
    src = [ $LKP_SRC/tests/${gcc_commit}.zip ];
    buildInputs = (oldAttrs.buildInputs or []) ++ [ flex ];
    nativeBuildInputs = (oldAttrs.nativeBuildInputs or []) ++ [ zip ];
EOF
if [ ${add_patch} -eq 1 ];then
  if [ ${gcc_major_ver} -eq 7 ];then
    echo "    patches = [ ${patch_path}/avoid-ustat-glibc-2.28.patch ]" >> ${overlays_path}/gcc_overlay.nix
  elif [ ${gcc_major_ver} -eq 8 ];then
    echo "    patches = [ ${patch_path}/fix-build-for-glibc-2.31.patch ]" >> ${overlays_path}/gcc_overlay.nix
  elif [ ${gcc_major_ver} -eq 11 ];then
    echo "    patches = [ ${patch_path}/libsanitizer-no-cyclades.patch ]" >> ${overlays_path}/gcc_overlay.nix 
  fi
  echo "      ++ (oldAttrs.patches or []);" >> ${overlays_path}/gcc_overlay.nix
fi
cat <<EOF>> ${overlays_path}/gcc_overlay.nix
  })));
}
EOF
}

generate_gcc_wrapper_overlays()
{
  cat > ${overlays_path}/gcc_wrapper_overlay.nix <<EOF
self : pkgs:
with pkgs;
{
  gcc${gcc_major_ver} = gcc${gcc_major_ver}.overrideAttrs (oldAttrs :{
    name = "gcc_wrapper_${gcc_commit}";
    version = "${gcc_version}";
  });
}
EOF
}

generate_gcc_build_nix()
{
  cat > ${nix_build_path}/gcc_build.nix <<EOF
let 
overlay1 = import ${overlays_path}/gcc_overlay.nix;
overlay2 = import ${overlays_path}/gcc_wrapper_overlay.nix;
pkgs = import <nixpkgs> { overlays = [ overlay1 overlay2 ]; };
in pkgs.gcc${gcc_major_ver}
EOF
}

generate_app_overlays()
{
  cat > ${overlays_path}/${app_name}_overlay.nix <<EOF
self: pkgs:
with pkgs;
{
  ${app_name} = ${app_name}.overrideAttrs (oldAttrs: rec {
    name = "${app_name}_${app_commit}";
    src = [ $LKP_SRC/tests/${app_commit}.zip];
    nativeBuildInputs = (oldAttrs.nativeBuildInputs or []) ++ [ zip ];
  });
}
EOF
}

generate_app_build_nix()
{
  cat > ${nix_build_path}/${app_name}_build.nix <<EOF
let
  overlay = import $overlays_path/${app_name}_overlay.nix;
  pkgs = import <nixpkgs> { overlays = [ overlay ];};
in pkgs.${app_name}.override
{
  stdenv  = pkgs.gcc${gcc_major_ver}Stdenv;
}
EOF
}

start_build_gcc()
{
  su ${nix_user} <<EOF
source /home/${nix_user}/.nix-profile/etc/profile.d/nix.sh
nix-build --show-trace ${nix_build_path}/gcc_build.nix
EOF
}

check_valid
create_nix_user
if [ ! -e /home/$nix_user/.nix-profile/bin/nix-build ];then
  uninstall_nix_env
  install_nix
  setup_nix_config
fi
init

# if gcc_commit isn't empty,we build gcc and recompile the app with this gcc
#if [ -n "$gcc_commit" ];then
#  find_conflict_insert_point
#  generate_gcc_overlays
#  generate_gcc_wrapper_overlays
#  generate_gcc_build_nix
#  start_build_gcc
#fi
# we start to recompile app with default gcc or pre-built gcc
generate_app_overlays
generate_app_build_nix
